#include <string>
#include <iostream>
#include <signal.h>
#include <sys/file.h>
#include <pthread.h>
#include "CTPServer.h"

using namespace std;

typedef IFAQuote* (*YCreateObject)(IQuoteEvent*pEvent);
typedef int (*YReleaseObject)(IFAQuote *pQuote);
typedef IServer*(*YSockServerCreateObject)(int port, IP_ADDRESS ipAddress, IServerHandle * pHandle);
typedef void (*YSockServerRun)();


#define QUOTE_SO ("libQuote.so")
#define SOCKSERVER_SO ("libSockServer.so")
#define CREATE_API ("CreateObject")
#define RELEASE_API ("ReleaseObject")
#define RUN_API ("Run")


IFAQuote * _pQuote = NULL;
CYKQuote * ykQuote = new CYKQuote();
YAutoDLL dll;

YReleaseObject _func2 = 0;
YCreateObject _func = 0;
YSockServerCreateObject _funcSockServer = 0;
YSockServerRun _funcSockRun = 0;

IServer *_pSockServer = 0;
YKSock * pSock = new YKSock();

typedef struct
{
	pthread_t thread_tid;  //thread id
	long thread_count;     //connection handled
}Thread;

void InitDaemon(int8_t nochdir, int8_t noclose)
{
	daemon(nochdir, noclose);

	//ignore signals
	signal(SIGINT, SIG_IGN);
	signal(SIGHUP, SIG_IGN);
	signal(SIGQUIT, SIG_IGN);
	signal(SIGPIPE, SIG_IGN);
	signal(SIGTTOU, SIG_IGN);
	signal(SIGTTIN, SIG_IGN);
	signal(SIGTERM, SIG_IGN);
}

int QuoteThread()
{
	printf("wait for init\n");
	//load so
	if (!_func)
	{
		printf("libQuote.so open fail\n");
		return 0;
	}

	_pQuote = _func(ykQuote);
	if (!_pQuote)
	{
		printf("%s,%d\n", __FUNCTION__, __LINE__);
		return 0;
	}

	printf("wait for connect\n");

	if (SUCCESS != _pQuote->Connect(URL_QUOTE))
	{
		printf("%s,%d\n", __FUNCTION__, __LINE__);
		return 0;
	}
		
	return 0;
}

int Release()
{
	/*
	release
	*/

	if (!_func2)
	{
		printf("[2]libQuote.so open fail\n");
		return 0;
	}
	_func2(_pQuote);

	if (ykQuote)
	{
		delete ykQuote;
		ykQuote = NULL;
	}

	printf("finish release\n");
	return 0;
}

void SockThread()
{
	YAutoDLL dll_socksvr;
	_funcSockServer = dll_socksvr.GetFunc<YSockServerCreateObject>(SOCKSERVER_SO, CREATE_API);
	_funcSockRun = dll_socksvr.GetFunc<YSockServerRun>(SOCKSERVER_SO, RUN_API);	
	_pSockServer = _funcSockServer(9999, IPV4, pSock);
	_funcSockRun();
	
}

void *thread_main(void *arg)
{
	int index = (u_int64_t)arg;
	printf("thread [%d] starting...\n", index);

	if (0 == index)
	{
		QuoteThread();
	}
	else if (1 == index)
	{
		SockThread();
	}

	return NULL;
}

int main(int argc, char *argv[])
{
	bool is_daemon = false;

	if (argc > 1)
	{
		if (0 == strcasecmp(argv[1], "-d"))
		{
			is_daemon = true;
		}
	}

	int lock_fd = open((const char *)argv[0], O_RDONLY);
	if (lock_fd < 0)
	{
		exit(1);
	}

	if (flock(lock_fd, LOCK_EX | LOCK_NB) < 0)
	{
		printf("Catalog Server was lauched!\n");
		exit(1);
	}

	if (is_daemon)
	{
		InitDaemon(1, 0);
	}


	_func = dll.GetFunc<YCreateObject>(QUOTE_SO, CREATE_API);
	_func2 = dll.GetFunc<YReleaseObject>(QUOTE_SO, RELEASE_API);

	//Init Quote
	int32_t iThreadCount = 2;
	Thread *tptr = new Thread[iThreadCount];
	for (int32_t i = 0; i < iThreadCount; ++i)
	{
		pthread_create(&tptr[i].thread_tid, NULL, &thread_main, (void*)i);
	}

	for (int32_t i = 0; i < iThreadCount; ++i)
	{
		pthread_join(tptr[i].thread_tid, NULL);
	}
	
	printf("input any key to release\n");
	getchar();
	Release();
	return 0;
}